package com.tjakus.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import com.tjakus.logging.Logging;
import com.tjakus.properties.Property;

/**
 * This class represents HTTP traffic manager which is responsible for sending
 * HTTP GET and HTTP POST requests
 * 
 * @author tjakus
 * 
 */

public class HttpTrafficManager {

	private static HttpClient httpclient;
	private static HttpGet httpget;
	private static HttpPost httpPost;
	private static HttpResponse response;
	private static HttpEntity entity;
	private static StringEntity postBody;

	/**
	 * This method initializes HTTP traffic manager (HttpClient)
	 * 
	 */
	public static void initializeHttpTrafficManager() {
		httpclient = new DefaultHttpClient();
		// Add proxy for ETK network
		if (Property.IS_PROXY_ENABLED.equalsIgnoreCase("TRUE")) {
			HttpHost proxy = new HttpHost(Property.PROXY_HOST, Property.PROXY_PORT,
					"http");
			httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
		}
	}

	/**
	 * This method sends HTTP GET request and returns cookie from 200 OK response
	 * 
	 */
	public static String sendHttpGetToGetCookies(String getUrl) {
		// send HTTP GET to get cookies
		try {
			Logging.getLogger().info(
					"HttpTrafficManager - sendHttpGetToGetCookies - [ " + getUrl + " ] ");

			httpget = new HttpGet(getUrl);
			response = httpclient.execute(httpget);

			// Printout response
			Logging.getLogger().debug(
					"HttpTrafficManager - sendHttpGetToGetCookies - [ "
							+ response.getStatusLine() + " ] ");

			// If response is not 200 OK return NULL
			if (response.getStatusLine().getStatusCode() != 200) {
				EntityUtils.consume(entity);
				return null;
			}

			// Get cookies from "Set-Cookie" header
			Header cookieHeader = response.getFirstHeader("Set-Cookie");
			Logging.getLogger().info(
					"HttpTrafficManager - sendHttpGetToGetCookies - [ "
							+ cookieHeader.getValue() + " ] ");

			entity = response.getEntity();
			EntityUtils.consume(entity);
			return cookieHeader.getValue();
		} catch (Exception e) {
			Logging
					.getLogger()
					.error(
							"HttpTrafficManager - sendHttpGetToGetCookies - [ Unable to get cookies ] ");
			Logging.getLogger().error(e);
			return null;
		}
	}

	/**
	 * This method sends HTTP GET request and returns body content from 200 OK
	 * response
	 */
	public static String sendHttpGet(String getUrl, String cookies) {
		// send HTTP GET
		try {
			Logging.getLogger().info(
					"HttpTrafficManager - sendHttpGet - [ " + getUrl + " ] ");

			httpget = new HttpGet(getUrl);
			httpget.addHeader("Cookie", cookies);
			response = httpclient.execute(httpget);
			entity = response.getEntity();
			String bodyData = null;

			// Printout response
			Logging.getLogger().debug(
					"HttpTrafficManager - sendHttpGet - [ " + response.getStatusLine()
							+ " ] ");

			// If response is not 200 OK return NULL
			if (response.getStatusLine().getStatusCode() != 200) {
				EntityUtils.consume(entity);
				return null;
			} else if (entity != null) {
				// If response is 200 OK and there is content
				InputStream instream = entity.getContent();
				Writer writer = new StringWriter();
				char[] buffer = new char[1024];
				Reader reader = new InputStreamReader(instream);
				int n;
				while ((n = reader.read(buffer)) != -1) {
					writer.write(buffer, 0, n);
				}
				bodyData = writer.toString();
				instream.close();
			}

			EntityUtils.consume(entity);

			return bodyData;
		} catch (IOException e) {
			Logging.getLogger().error(
					"HttpTrafficManager - sendHttpGet - [ Unable to send Http get ] ");
			Logging.getLogger().error(e);
			return null;
		}
	}

	/**
	 * This method sends HTTP POST request with string content data in its body
	 * 
	 */
	public static boolean sendHttpPostWithStringContent(String httpPostUrl,
			String cookies, String postContent) {
		// HTTP POST request with string content
		try {
			Logging.getLogger().info(
					"HttpTrafficManager - sendHttpPostWithStringContent - [ "
							+ httpPostUrl + " ] ");

			httpPost = new HttpPost(httpPostUrl);
			httpPost.addHeader("Cookie", cookies);
			postBody = new StringEntity(postContent);
			postBody.setContentType("application/x-www-form-urlencoded");
			httpPost.setEntity(postBody);

			response = httpclient.execute(httpPost);
			entity = response.getEntity();
			EntityUtils.consume(entity);

			// Printout response
			Logging.getLogger().debug(
					"HttpTrafficManager - sendHttpPostWithStringContent - [ "
							+ response.getStatusLine() + " ] ");
			if ((response.getStatusLine().getStatusCode() == 301)
					|| (response.getStatusLine().getStatusCode() == 302)
					|| (response.getStatusLine().getStatusCode() == 200)) {
				return true;
			} else {
				return false;
			}
		} catch (IOException e) {
			Logging
					.getLogger()
					.error(
							"HttpTrafficManager - sendHttpPostWithStringContent - [ Unable to send Http post with string content ] ");
			Logging.getLogger().error(e);
			return false;
		}
	}

	/**
	 * This method sends HTTP POST request with MIME content data in its body
	 * 
	 */
	public static boolean sendHttpPostWithMimeContent(String postUrl,
			String cookies, MultipartEntity mimeEntity) {
		// HTTP POST request with MIME content
		try {
			Logging.getLogger().info(
					"HttpTrafficManager - sendHttpPostWithMimeContent - [ " + postUrl
							+ " ] ");

			httpPost = new HttpPost(postUrl);
			httpPost.addHeader("Cookie", cookies);
			postBody.setContentType("multipart/form-data");
			httpPost.setEntity(postBody);
			httpPost.setEntity(mimeEntity);
			response = httpclient.execute(httpPost);

			entity = response.getEntity();
			EntityUtils.consume(entity);

			// Printout response
			Logging.getLogger().debug(
					"HttpTrafficManager - sendHttpPostWithMimeContent - [ "
							+ response.getStatusLine() + " ] ");
			if ((response.getStatusLine().getStatusCode() == 302)
					|| (response.getStatusLine().getStatusCode() == 200)) {
				return true;
			} else {
				return false;
			}
		} catch (IOException e) {
			Logging
					.getLogger()
					.error(
							"HttpTrafficManager - sendHttpPostWithMimeContent - [ Unable to send Http post with MIME content ] ");
			Logging.getLogger().error(e);
			return false;
		}
	}

	/**
	 * This method closes all HTTP connection (HttpClient)
	 * 
	 */
	public static void closeAllConnections() {
		httpclient.getConnectionManager().shutdown();
	}

}
